package org.knot.autojmx.metadata;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * autojmx Metadata 
 * 
 * @author <a href="mailto:yuxiaoweimail@gmail.com">yuxiaowei</a>
 */
public class AutoJMXFieldMap {
	
	protected final Log logger = LogFactory.getLog(getClass());
	
	private Map<String, PropertyField> m_properties = new HashMap<String, PropertyField>();
	 
	private Map<String, MethodField[]> m_methods = new HashMap<String, MethodField[]>();
	 
	private Map<String, NotificationField> m_notifications = new HashMap<String, NotificationField>();
	 
	private String m_description;

	public String getDecription() {
		return m_description;
	}

	public void setDescription(String description) {
		this.m_description = description;
	}

	/**
	 * 增加属性
	 * 
	 * @param name 属性名
	 * @param propertyField
	 */
	public void addPropertyFromName(String name, PropertyField propertyField) {
		m_properties.put(name, propertyField);
	}

	/**
	 * 获取全部属性
	 */
	public Collection<PropertyField> getProperties() {
		if (m_properties != null) {
			return m_properties.values();
		} else {
			return null;
		}
	}

	/**
	 * 获取属性通过name
	 */
	public PropertyField getPropertyFromName(String name) {
		PropertyField prop = m_properties.get(name);
		return prop;
	}

	/**
	 * 获取属性通过field name
	 */
	public PropertyField getPropertyFromField(String field) {
		PropertyField property = null;
		Iterator<PropertyField> it = m_properties.values().iterator();
		while (it.hasNext()) {
			PropertyField p = it.next();
			if (p.getField().getName().compareTo(field) == 0) {
				property = p;
			}
		}
		return property;
	}

	/**
	 * 增加方法
	 */
	public void addMethodFromName(String name, MethodField methodField) {
		MethodField[] mf;
		if (!m_methods.containsKey(name)) {
			mf = new MethodField[1];
			mf[0] = methodField;
		} else {
			MethodField[] temp = m_methods.get(name);
			mf = new MethodField[temp.length + 1];
			for (int i = 0; i < temp.length; i++) {
				mf[i] = temp[i];
			}
			mf[temp.length] = methodField;
		}
		m_methods.put(name, mf);
	}

	/**
	 * 增加方法集合
	 */
	public void addMethodFromName(String name, MethodField[] methodsField) {
		MethodField[] mf;
		if (!m_methods.containsKey(name)) {
			mf = methodsField;
		} else {
			MethodField[] temp = m_methods.get(name);
			mf = new MethodField[temp.length + methodsField.length];
			for (int i = 0; i < temp.length; i++) {
				mf[i] = temp[i];
			}
			for (int i = 0; i < methodsField.length; i++) {
				mf[i + temp.length] = methodsField[i];
			}
		}
		m_methods.put(name, mf);
	}

	/**
	 * 增加或覆盖方法集合
	 */
	public void overrideMethodFromName(String name, MethodField methodField) {
		MethodField[] mf = new MethodField[1];
		mf[0] = methodField;
		m_methods.put(name, mf);
	}

 
	public void overrideMethodFromName(String name, MethodField[] methodsField) {
		m_methods.put(name, methodsField);
	}

	 
	public MethodField[] getMethodFromName(String name) {
		MethodField[] prop = m_methods.get(name);
		return prop;
	}

	 
	public MethodField getMethodFromName(String operationName, String[] signature) {
		MethodField[] methods = m_methods.get(operationName);
		for (int i = 0; i < methods.length; i++) {
			if (isSameSignature(signature, methods[i]
					.getMethod().getParameterTypes())) {
				return methods[i];
			}
		}
		return null;
	}

	 
	private boolean isSameSignature(String[] sig1, Class[] sig2) {
		if (sig1.length != sig2.length) {
			return false;
		} else {
			for (int i = 0; i < sig1.length; i++) {
				if (!sig1[i].equalsIgnoreCase(sig2[i].getName())) {
					return false;
				}
			}

		}
		return true;
	}

	 
	public Collection<MethodField[]> getMethods() {
		if (m_methods != null) {
			return m_methods.values();
		} else {
			return null;
		}
	}

	public void addNotificationFromName(String name,
			NotificationField notificationField) {
		m_notifications.put(name, notificationField);
	}
 
	public NotificationField getNotificationFromName(String name) {
		NotificationField prop = m_notifications.get(name);
		return prop;
	}

	public Collection<NotificationField> getNotifications() {
		if (m_notifications != null) {
			return m_notifications.values();
		} else {
			return null;
		}
	}
}
